#ifndef NODE_H
#define NODE_H
#include "vector.h"

/* abstract syntax tree */
typedef enum nodetype
{
  /* leaf nodes */
  NODETYPE_NULL,
  NODETYPE_INTEGER,
  NODETYPE_REAL,
  NODETYPE_STRING,
  NODETYPE_IDENTIFIER,
  NODETYPE_SYMBOL,
  
  /* internal nodes */
  NODETYPE_RkVECTOR,
  NODETYPE_FN_CALL,
  NODETYPE_EQUAL,
  NODETYPE_NOT_EQUAL,
  NODETYPE_AND,
  NODETYPE_OR,
  NODETYPE_CPD_CALL,
  NODETYPE_IF,                                  /* if statement */
  NODETYPE_DET_DEP,                             /* deterministic dependency */
  NODETYPE_STO_DEP,                             /* stochastic dependency */
  NODETYPE_SET_IMP,                             /* implicit set of objects */
  NODETYPE_SET_EXP,                             /* explicit set of objects */
  NODETYPE_SET_CARD,                             /* cardinality of a set */
  
  NODETYPE_LIST
} nodetype;

typedef union nodeleaf
{
  int             intval;
  double          doubleval;
  char          * pchar;
  struct symbol * psym;
} nodeleaf;

typedef struct node
{
  nodetype   type;
  char     * fname;                          /* file name */
  int        lnum;                           /* line number */
  void     * childlist;           /* list of children, null if leaf */
  nodeleaf   leaf;                 /* only used if childlist is null */
  struct symbol * valtype;                   /* type of the value */
  struct symbol * reqtype;                   /* requested type of the value */
  char     * genname;                        /* generated name if any */
} node;


#define NODE_IS_LEAF(node) (NULL == (node)->childlist)

/* arglist is owned by the node */
node * node_alloc(nodetype type, void * childlist, char * filename,
                  int linenum);

/* any pointers in leaf are owned by node */
node * nodeleaf_alloc(nodetype type, nodeleaf leaf, char * filename,
                      int linenum);

/* print a node and its subtree */
void node_print(node * node1);

/* get an Real from a node, return an error if it's of the wrong type
 * a NATURAL is also acceptable */
double node_get_real(node * node1);

/* get an RkVector from a node, return an error if it's of the wrong type */
vector * node_get_rkvector(node * node1);

/* raise an error on the specified node and exit */
void * node_error(node * node1, char * fmt, ...);

#endif /* NODE_H */
